home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2007 September / PCWSEP07.iso / Software / Linux / Linux Mint 3.0 Light / LinuxMint-3.0-Light.iso / casper / filesystem.squashfs / lib / udev / path_id < prev    next >
Encoding:
Text File  |  2007-04-10  |  11.4 KB  |  565 lines

  1. #!/bin/sh
  2.  
  3. # provide the shortest possible unique hardware path to a device
  4. # for the Linux Persistent Device Naming scheme
  5. #
  6. # Copyright (C) 2005-2006 SUSE Linux Products GmbH
  7. # Author:
  8. #    Hannes Reinecke <hare@suse.de>
  9. #
  10. #    This program is free software; you can redistribute it and/or modify it
  11. #    under the terms of the GNU General Public License as published by the
  12. #    Free Software Foundation version 2 of the License.
  13. #
  14. # to be called from a udev rule to return the name for a symlink
  15. #    DEVPATH=<devpath>; path_id
  16. #    path_id <devpath>
  17.  
  18. # examples for all block devices on a system:
  19. #    for i in `find /sys/class/block`; do DEVPATH="`echo $i | sed -e 's@^/sys\|/dev@@g'`"; path_id; done
  20.  
  21. SYSFS=/sys
  22. RESULT=1
  23. TYPE=
  24. OPWD="`pwd`"
  25. full_sysfs_path=
  26. full_sysfs_device_path=
  27.  
  28. if [ -z "$DEVPATH" -a -z "$1" ] ; then
  29.     exit 1
  30. fi
  31.  
  32. if [ -z "$DEVPATH" ] ; then
  33.     case "$1" in
  34.         $SYSFS/*)
  35.             DEVPATH="${1#$SYSFS}"
  36.             ;;
  37.         *)
  38.             DEVPATH=$1
  39.             ;;
  40.     esac
  41. fi
  42.  
  43. if [ ! -e $SYSFS$DEVPATH/dev ] ; then
  44.     exit 1
  45. fi
  46.  
  47. case "$DEVPATH" in
  48.     /devices/*)
  49.         cd "$SYSFS$DEVPATH/subsystem";
  50.         TYPE="`pwd -P`"
  51.         cd "$OPWD"
  52.         TYPE="${TYPE##*/}"
  53.         ;;
  54.     /class/*)
  55.         TYPE="${DEVPATH#/class/}"
  56.         TYPE="${TYPE%%/*}"
  57.         ;;
  58.     /block/*)
  59.         TYPE=block
  60.         ;;
  61.     *)
  62.         exit 1
  63.         ;;
  64. esac
  65.  
  66. get_port_offset () {
  67.     local type offset port
  68.     type=$1
  69.     offset=$2
  70.     for i in $type[0-9]* ; do
  71.         : i $i
  72.         port="${i#$type}"
  73.         if [ "$port" -lt "$offset" ] ; then offset=$port ; fi
  74.     done
  75.     echo $offset
  76. }
  77.  
  78. handle_pci () {
  79.     local DEV=$1
  80.     cd -P $1
  81.     DEV=${PWD}
  82.     pci_id=${DEV##*/}
  83.     host_dev_path=$DEV
  84.     while [ ! -z "$host_dev_path" ] ; do
  85.         case "$host_dev_path" in
  86.             */pci[0-9]*)
  87.                 host_dev_path=${host_dev_path%/*}
  88.                 ;;
  89.             *)
  90.                 break
  91.                 ;;
  92.         esac
  93.     done
  94.     d="pci-$pci_id-$d"
  95.     D="$host_dev_path"
  96.     RESULT=0
  97. }
  98.  
  99. handle_platform () {
  100.     local DEV=$1
  101.     cd -P $1
  102.     DEV=${PWD}
  103.     platform_id=${DEV##*/}
  104.     host_dev_path=$DEV
  105.     while [ ! -z "$host_dev_path" ] ; do
  106.         case "$host_dev_path" in
  107.             */platform*)
  108.                 host_dev_path=${host_dev_path%/*}
  109.                 ;;
  110.             *)
  111.                 break
  112.                 ;;
  113.         esac
  114.     done
  115.     if [ "$d" ]; then
  116.         d="platform-$platform_id-$d"
  117.     else
  118.         d="platform-$platform_id"
  119.     fi
  120.     D="$host_dev_path"
  121.     RESULT=0
  122. }
  123.  
  124. handle_serio () {
  125.     local DEV=$1
  126.     cd -P $1
  127.     DEV=${PWD}
  128.     serio_id=${DEV##*/serio}
  129.     host_dev_path=$DEV
  130.     while [ ! -z "$host_dev_path" ] ; do
  131.         case "$host_dev_path" in
  132.             */serio*)
  133.                 host_dev_path=${host_dev_path%/*}
  134.                 ;;
  135.             *)
  136.                 break
  137.                 ;;
  138.         esac
  139.     done
  140.     if [ "$d" ]; then
  141.         d="serio-$serio_id-$d"
  142.     else
  143.         d="serio-$serio_id"
  144.     fi
  145.     D="$host_dev_path"
  146.     RESULT=0
  147. }
  148.  
  149. handle_ide () {
  150.     : handle_ide $*
  151.     local DEV=$1
  152.     local port idedev idecontroller
  153.     # IDE
  154.     : DEV $DEV
  155.     port=${DEV##*/}
  156.     idedev=${DEV%/*}
  157.     idecontroller=${idedev%/*}
  158.     # port info if the controller has more than one interface
  159.     port="${port#ide}"
  160.     : port $port d $d
  161.     : idedev $idedev kernel_port $port
  162.     case "${port#*.}" in
  163.         0)
  164.             channel=0
  165.             ;;
  166.         1)
  167.             channel=1
  168.             ;;
  169.         *)
  170.             echo "Error: $idedev is neither master or slave" >&2
  171.             ;;
  172.     esac
  173.     cd $idecontroller
  174.     offset="`get_port_offset ide ${port%.*}`"
  175.     cd "$OPWD"
  176.     :  port offset $offset
  177.     port=$((${port%.*} - $offset))
  178.     if [ "$d" ] ; then
  179.         d="ide-${port}:$channel-$d"
  180.     else
  181.         d="ide-${port}:$channel"
  182.     fi
  183.     D=$idecontroller
  184.     RESULT=0
  185. }
  186.  
  187. handle_scsi () {
  188.     : handle_scsi $*
  189.     local DEV=$1
  190.     local cil controller_port controller_dev
  191.     # SCSI device
  192.     cil="${DEV##*/}"
  193.     cil="${cil#*:}"
  194.     target_dev=${DEV%/*}
  195.     target_id=${target_dev##*/target}
  196.     cd "$target_dev"
  197.     target_num=0
  198.     for tid in ${target_id}* ; do
  199.         target_num=$(( $target_num + 1 ))
  200.     done
  201.     controller_port=${target_dev%/*}
  202.     controller_dev="${controller_port%/*}"
  203.     : controller_dev $controller_dev
  204.     : controller_port $controller_port
  205.     # a host controller may have more than one interface/port
  206.     controller_port="${controller_port##*/host}"
  207.     #
  208.     cd "$controller_dev"
  209.     controller_offset=$(get_port_offset host $controller_port)
  210.     cd "$OPWD"
  211.     controller_port=$(( $controller_port - $controller_offset))
  212.     scsi_id="scsi-${controller_port}:${cil}"
  213.     if [ "$d" ] ; then
  214.         d="${scsi_id}-$d"
  215.     else
  216.         d="$scsi_id"
  217.     fi
  218.     D="$controller_dev"
  219.     RESULT=0
  220. }
  221.  
  222. handle_firewire () {
  223.     : handle_firewire $*
  224.     local DEV=$1
  225.     if [ -f "$D/ieee1394_id" ] ; then
  226.         read ieee1394_id < $D/ieee1394_id
  227.     fi
  228.     if [ -z "$ieee1394_id" ] ; then
  229.         : no IEEE1394 ID
  230.         RESULT=1
  231.         return
  232.     fi
  233.     fw_host_dev=${DEV%/fw-host*}
  234.     # IEEE1394 devices are always endpoints
  235.     d="ieee1394-0x$ieee1394_id"
  236.     D="$fw_host_dev"
  237.     RESULT=0
  238. }
  239.  
  240. handle_fc () {
  241.     : handle_fc $*
  242.     local DEV=$1
  243.     local cil controller_port controller_dev
  244.     # SCSI-FC device
  245.     fc_tgt_hcil="${DEV##*/}"
  246.     fc_tgt_lun="${fc_tgt_hcil##*:}"
  247.     fc_tgt_path="${DEV%/*}"
  248.     fc_tgt_num="${fc_tgt_path##*/}"
  249.     fc_tgt_dev="${fc_tgt_path}/fc_transport:${fc_tgt_num}"
  250.     if [ -e "$fc_tgt_dev/port_name" ]; then
  251.         read wwpn < $fc_tgt_dev/port_name
  252.     fi
  253.     if [ -z "$wwpn" ] ; then
  254.         : no WWPN
  255.         D=
  256.         RESULT=1
  257.         return
  258.     fi
  259.     # Linux currently knows about 32bit luns
  260.     tmp_lun3=$(printf "%04x" $(($fc_tgt_lun & 0xFFFF)))
  261.     tmp_lun2=$(printf "%04x" $(( ($fc_tgt_lun >> 16) & 0xFFFF)))
  262.     tmp_lun1="0000"
  263.     tmp_lun0="0000"
  264.     if (($fc_tgt_lun == 0)) ; then
  265.         lun="0x0000000000000000"
  266.     else
  267.         lun="0x${tmp_lun3}${tmp_lun2}${tmp_lun1}${tmp_lun0}"
  268.     fi
  269.     controller_dev="${fc_tgt_path%/host[0-9]*}"
  270.     # FC devices are always endpoints
  271.     d="fc-${wwpn}:${lun}"
  272.     D="$controller_dev"
  273.     RESULT=0
  274. }
  275.  
  276. handle_sas () {
  277.     : handle_sas $*
  278.     local DEV=$1
  279.     local cil adapter controller_dev
  280.     # SAS device
  281.     sas_host_path="${DEV%%/port*}"
  282.     sas_phy_path="${DEV#*/host*/}"
  283.     sas_phy_path="${sas_phy_path%%/target*}"
  284.     sas_phy_id="${sas_phy_path%%/*}"
  285.     sas_phy_id="${sas_phy_id##*port-}"
  286.     sas_port_id="${sas_phy_path%%/end_device*}"
  287.     sas_port_id="${sas_port_id##*port-}"
  288.     sas_end_id="${sas_phy_path##*end_device-}"
  289.     sas_phy_dev="/sys/class/sas_phy/phy-${sas_phy_id}"
  290.     if [ -e "$sas_phy_dev/sas_address" ]; then
  291.         read phy_address < $sas_phy_dev/sas_address
  292.         read phy_id < $sas_phy_dev/phy_identifier
  293.     fi
  294.     if [ -z "$phy_address" ] ; then
  295.         : no initiator address
  296.         D=
  297.         RESULT=1
  298.         return
  299.     fi
  300.     sas_port_dev="/sys/class/sas_port/port-${sas_port_id}"
  301.     if [ -e "$sas_port_dev/num_phys" ] ; then
  302.         read phy_port < $sas_port_dev/num_phys
  303.     fi
  304.     if [ -z "$phy_port" ] ; then
  305.         : no initiator address
  306.         D=
  307.         RESULT=1
  308.         return
  309.     fi
  310.     sas_phy_address="$phy_address:$phy_port:$phy_id"
  311.     sas_end_dev="/sys/class/sas_device/end_device-${sas_end_id}"
  312.     if [ -e "$sas_end_dev/sas_address" ]; then
  313.         read end_address < $sas_end_dev/sas_address
  314.         read end_id < $sas_end_dev/phy_identifier
  315.     fi
  316.     if [ -z "$end_address" ] ; then
  317.         : no initiator address
  318.         D=
  319.         RESULT=1
  320.         return
  321.     fi
  322.     sas_end_address="$end_address:$end_id"
  323.     controller_dev="${sas_host_path%/host[0-9]*}"
  324.     # SAS devices are always endpoints
  325.     d="sas-${sas_phy_address}-${sas_end_address}"
  326.     D="$controller_dev"
  327.     RESULT=0
  328. }
  329.  
  330. handle_iscsi() {
  331.     local DEV=$1
  332.     local iscsi_session_dir
  333.     local iscsi_session iscsi_session_path
  334.     local iscsi_connection iscsi_connection_path
  335.     local iscsi_scsi_lun
  336.     # iSCSI device
  337.     iscsi_session_dir="${DEV%%/target*}"
  338.     iscsi_session="${iscsi_session_dir##*/}"
  339.     iscsi_session_path=/sys/class/iscsi_session/${iscsi_session}
  340.     if [ ! -d "$iscsi_session_path" ] ; then
  341.         : no iSCSI session path
  342.         RESULT=1
  343.         return
  344.     fi
  345.     # Currently we're not doing MC/S
  346.     for conn in ${iscsi_session_dir}/connection* ; do
  347.         iscsi_conn_num=${conn##*:}
  348.         if [ "$iscsi_conn_num" = '0' ] ; then
  349.         iscsi_connection=$(basename $conn)
  350.         fi
  351.     done
  352.     if [ -z "$iscsi_connection" ] ; then
  353.         : no iSCSI connection found
  354.         RESULT=1
  355.         return
  356.     fi
  357.     iscsi_connection_path=/sys/class/iscsi_connection/${iscsi_connection}
  358.     if [ ! -d "$iscsi_connection_path" ] ; then
  359.         : no iSCSI connection path
  360.         RESULT=1
  361.         return
  362.     fi
  363.     if [ -e "${iscsi_session_path}/targetname" ]; then
  364.         read iscsi_tgtname < ${iscsi_session_path}/targetname
  365.     fi
  366.     if [ -z "$iscsi_tgtname" ] ; then
  367.         : No iSCSI Targetname
  368.         RESULT=1
  369.         return
  370.     fi
  371.     if [ -e "${iscsi_connection_path}/persistent_address" ] ; then
  372.         read iscsi_address < ${iscsi_connection_path}/persistent_address
  373.     fi
  374.     if [ -z "$iscsi_address" ] ; then
  375.         : No iSCSI Target address
  376.         RESULT=1
  377.         return
  378.     fi
  379.     if [ -e "${iscsi_connection_path}/persistent_port" ] ; then
  380.         read iscsi_port < ${iscsi_connection_path}/persistent_port
  381.     fi
  382.     iscsi_scsi_lun="${DEV##*:}"
  383.     d="ip-${iscsi_address}:${iscsi_port}-iscsi-${iscsi_tgtname}-lun-${iscsi_scsi_lun}"
  384.     RESULT=0
  385. }
  386.  
  387. handle_usb () {
  388. : handle_usb $*
  389.     local DEV=$1
  390.     cd -P $1
  391.     DEV=${PWD}
  392.     port_id=${DEV##*/}
  393.     port_num=${port_id#*-}
  394.     host_dev_path=$DEV
  395.     while [ ! -z "$host_dev_path" ] ; do
  396.         case "$host_dev_path" in
  397.             */usb*)
  398.                 usb_host_path=$host_dev_path
  399.                 host_dev_path="${host_dev_path%/*}"
  400.                 ;;
  401.             *)
  402.                 break
  403.                 ;;
  404.         esac
  405.     done
  406.     : host_dev_path $host_dev_path
  407.     usb_host_num=${usb_host_path##*/usb}
  408.  
  409.     cd "$host_dev_path"
  410.     usb_host_offset=$(get_port_offset usb $usb_host_num)
  411.     usb_host_port=$(($usb_host_num - $usb_host_offset))
  412.     cd "$OPWD"
  413.     if [ "$d" ] ; then
  414.         d="usb-$usb_host_port:$port_num-${d}"
  415.     else
  416.         d="usb-$usb_host_port:$port_num"
  417.     fi
  418.     D="$host_dev_path"
  419.     RESULT=0
  420. }
  421.  
  422. handle_device () {
  423.     full_sysfs_path="$SYSFS$DEVPATH"
  424.     case "$DEVPATH" in
  425.         /devices/*)
  426.             # new sysfs layout
  427.             if [ -L $full_sysfs_path/subsystem ]; then
  428.                 full_sysfs_path="${full_sysfs_path%/*}"
  429.                 cd "$full_sysfs_path/subsystem";
  430.                 subsys="`pwd -P`"
  431.                 cd "$OPWD"
  432.                 subsys="${subsys##*/}"
  433.                 if [ "$subsys" = "block" ]; then
  434.                     # parent is "block", it's a partition, move one up
  435.                 full_sysfs_path="${full_sysfs_path%/*}"
  436.                 fi
  437.                 cd $full_sysfs_path
  438.             fi
  439.             ;;
  440.         *)
  441.             # old sysfs layout
  442.             if [ ! -L $full_sysfs_path/device ] ; then
  443.                 if [ -f $full_sysfs_path/range ] ; then return ; fi
  444.                 full_sysfs_path="${full_sysfs_path%/*}"
  445.                 : full_sysfs_path "$full_sysfs_path"
  446.                 if [ ! -L $full_sysfs_path/device -o ! -f $full_sysfs_path/dev ] ; then
  447.                     return
  448.                 fi
  449.             fi
  450.             cd $full_sysfs_path/device
  451.             ;;
  452.     esac
  453.     full_sysfs_device_path="`pwd -P`"
  454.     cd "$OPWD"
  455.     D=$full_sysfs_device_path
  456.     while [ ! -z "$D" ] ; do
  457.         case "$D" in
  458.             */ide[0-9]/[0-9].[0-9]*|*/ide[0-9][0-9]/[0-9][0-9].[0-9]*)
  459.                 handle_ide "$D"
  460.                 ;;
  461.             */css0/*)
  462.                 if [ -r $full_sysfs_device_path/wwpn ]; then
  463.                     read wwpn < $full_sysfs_device_path/wwpn
  464.                 fi
  465.                 if [ -r $full_sysfs_device_path/fcp_lun ]; then
  466.                     read lun < $full_sysfs_device_path/fcp_lun
  467.                 fi
  468.                 if [ -r $full_sysfs_device_path/hba_id ]; then
  469.                     read bus_id < $full_sysfs_device_path/hba_id
  470.                 fi
  471.                 if [ "$bus_id" -a "$wwpn" -a "$lun" ]; then
  472.                     # S/390 zfcp adapter
  473.                     d="ccw-$bus_id-zfcp-$wwpn:$lun"
  474.                     RESULT=0
  475.                 else
  476.                     # DASD devices
  477.                     bus="ccw"
  478.                     adapter=${D##*/}
  479.                     d="$bus-$adapter"
  480.                     RESULT=0
  481.                 fi
  482.                 D=
  483.                 ;;
  484.             */rport-[0-9]*:[0-9]*-[0-9]*/*)
  485.                 handle_fc "$D"
  486.                 ;;
  487.             */end_device-[0-9]*:[0-9]*:[0-9]*/*)
  488.                 handle_sas "$D"
  489.                 ;;
  490.             */fw-host[0-9]*/*)
  491.                 handle_firewire "$D"
  492.                 ;;
  493.             */session[0-9]*/*)
  494.                 handle_iscsi "$D"
  495.                 D=
  496.                 ;;
  497.             */host[0-9]*/[0-9]*:[0-9]*:[0-9]*:[0-9]*)
  498.                 handle_scsi "$D"
  499.                 ;;
  500.             */usb[0-9]*/[0-9]*/*)
  501.                 handle_usb "$D"
  502.                 ;;
  503.             */pci[0-9]*:[0-9]*)
  504.                 handle_pci "$D"
  505.                 ;;
  506.             */serio[0-9]*)
  507.                 handle_serio "$D"
  508.                 ;;
  509.             */platform/*)
  510.                 handle_platform "$D"
  511.                 ;;
  512.             */devices)
  513.                 D=
  514.                 ;;
  515.             *)
  516.                 : not handled
  517.                 RESULT=1
  518.                 return
  519.                 ;;
  520.         esac
  521.     done
  522.     if [ "$TYPE" = "scsi_tape" ] ; then
  523.         devname=${full_sysfs_path##*/}
  524.         rewind="${devname%%st*}"
  525.         mode="${devname##*st}"
  526.         case "$mode" in
  527.             *l)
  528.                 mode="l"
  529.                 ;;
  530.             *m)
  531.                 mode="m"
  532.                 ;;
  533.             *a)
  534.                 mode="a"
  535.                 ;;
  536.             *)
  537.                 mode=""
  538.                ;;
  539.         esac
  540.         if [ "$d" ]; then
  541.             d="$d-${rewind}st${mode}"
  542.         fi
  543.     fi
  544. }
  545.  
  546. case "$TYPE" in
  547.     block)
  548.         handle_device
  549.         echo "ID_PATH=$d"
  550.         ;;
  551.     scsi_tape)
  552.         handle_device
  553.         echo "ID_PATH=$d"
  554.         ;;
  555.     input)
  556.         handle_device
  557.         echo "ID_PATH=$d"
  558.         ;;
  559.     *)
  560.         RESULT=1
  561.         ;;
  562. esac
  563.  
  564. exit $RESULT
  565.